package vno.sci.mapEditor
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.ui.Keyboard;
	import flash.utils.ByteArray;
	
	import flashx.textLayout.elements.BreakElement;
	import flashx.textLayout.formats.BackgroundColor;
	
	import hr.binaria.asx3m.Asx3mer;
	
	import mx.skins.Border;
	
	import org.aswing.ASFont;
	import org.aswing.BorderLayout;
	import org.aswing.DefaultBoundedRangeModel;
	import org.aswing.JButton;
	import org.aswing.JPanel;
	import org.aswing.JPopup;
	import org.aswing.JTextField;
	import org.aswing.SoftBoxLayout;
	
	import vno.fux.res.manager.CommonLoader;
	import vno.fux.res.manager.DataLoader;
	import vno.fux.res.manager.ResourceMission;
	import vno.fux.res.pool.AutoBitmap;
	import vno.fux.res.pool.BitmapAttacher;
	import vno.fux.res.pool.BitmapTarget;
	

		/**
		 * 使用方法，
		 * save为存
		 * load为读
		 * 存的读的文件长宽必须一样
		 * undo为撤消，注意监听的是MOUSE_UP事件，所以鼠标在这个按钮上抬起就执行了一次撤消
		 * 文本框为标签
		 * 单击鼠标为做标记，文本同文本框里的内容
		 * Ctrl+拖动可以改变点的位置，同时文本框里显示该点里的标记文本
		 * Alt+单击为删除这个标记
		 * Shift+单击为把这个标记的文本替换为文本框里的文本
		 * 
		 * 鼠标滚轮移动
		 * Ctrl+鼠标滚轮横向移动
		 */		
	public class MapMarker extends Sprite
	{		

		private var _map:BitmapAttacher = new BitmapAttacher;
		private var _text:JTextField = new JTextField("",20);
		private var _popup:JPopup;
		
		public var _inner:Inner;
		private var _label:JTextField = new JTextField();
		
		public function MapMarker()
		{
			var autoBitmap:AutoBitmap = new AutoBitmap();
			autoBitmap.attach(_map);
			var loader:CommonLoader = new CommonLoader();
			var mission:ResourceMission = new ResourceMission("file:///C:/Users/scinart/Pictures/map.jpg", autoBitmap, CommonLoader.PIC);
			loader.load(mission);
			
			loader.addEventListener(Event.COMPLETE, start);
		}
		private function start(e:Event):void
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;

			_popup = new JPopup(this);
			_inner = new Inner(_text, _map);
			
			
			_popup.setLayout(new BorderLayout());
			_popup.setSizeWH(_map.width, _map.height);
			
			_popup.addChild(_inner);

			_popup.show();
			this.addChild(_popup);
			this.addUI();
		}
		
		private function addUI():void
		{
			var jsave:JButton = new JButton("Save");
			jsave.addEventListener(MouseEvent.MOUSE_UP,function (e:Event):void{_inner.UIsave(Inner.BINARY_TYPE);});
			var jload:JButton = new JButton("Load");
			jload.addEventListener(MouseEvent.MOUSE_UP,function (e:MouseEvent):void{_inner.UIload(Inner.BINARY_TYPE);});
			var jsaveXml:JButton = new JButton("SaveXML");
			jsaveXml.addEventListener(MouseEvent.MOUSE_UP, function (e:MouseEvent):void{_inner.UIsave(Inner.XML_TYPE);});
			var jloadXml:JButton = new JButton("LoadXML");
			jloadXml.addEventListener(MouseEvent.MOUSE_UP, function (e:MouseEvent):void{_inner.UIload(Inner.XML_TYPE);});
			
			var undo:JButton = new JButton("Undo");
			undo.addEventListener(MouseEvent.MOUSE_UP, function (e:MouseEvent):void{_inner.undo();});	
			
			var panel:JPanel = new JPanel(new SoftBoxLayout());
			panel.appendAll(jsave, jload, jsaveXml, jloadXml, undo,_text);
			_popup.append(panel,BorderLayout.NORTH);
			
		}
		private function onKeyUp(e:KeyboardEvent):void
		{
			if(e.keyCode == Keyboard.Z)
			{
				_inner.undo();
			}
			if(e.keyCode == Keyboard.U)
			{
				_inner.undo();
			}
			if(e.keyCode == Keyboard.S)
			{
				_inner.UIsave();
			}
			if(e.keyCode == Keyboard.L)
			{
				_inner.UIload();
			}
		}
		
		
		
		private function onKeyDown(e:KeyboardEvent):void //OK
		{	
			var factor:int = 4;
			if(e.shiftKey)
			{
				factor /= 2;
			}
			if(e.altKey)
			{
				factor *= 3;
			}
			if(e.keyCode == Keyboard.UP)
			{
				_inner.y += _inner.blockWidth*factor;
			}
			if(e.keyCode == Keyboard.DOWN)
			{			
				_inner.y -= _inner.blockWidth*factor;
			}
			if(e.keyCode == Keyboard.LEFT)
			{
				_inner.x += _inner.blockWidth*factor;
			}
			if(e.keyCode == Keyboard.RIGHT)
			{
				_inner.x -= _inner.blockWidth*factor;
			}
		}
	}
}
import flash.display.Bitmap;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.net.FileReference;
import flash.ui.Keyboard;
import flash.utils.ByteArray;

import hr.binaria.asx3m.Asx3m;
import hr.binaria.asx3m.Asx3mer;

import org.aswing.JTextField;

class Inner extends Sprite
{
	
	public static const BINARY_TYPE:String = "binary";
	public static const XML_TYPE:String = "xml";
	
	private var mapWidth:int;
	private var mapHeight:int;
	public var blockWidth:int = 10;
	public var blockHeight:int = 10;
	private var radius:int = 8;
	
	private var downEvent:MouseEvent;
	private var upEvent:MouseEvent;
	
	public var shapes:Array = new Array();
	public var shapesInfo:Array = new Array();
	public var associateInfo:Array = new Array();
	// 结构，array[beginX, beginY, radius, label:String];
	
	public var label:JTextField;
	private var map:Bitmap;
	
	public function Inner(l:JTextField, m:Bitmap)
	{
		this.label = l;
		this.map = m;
		
		this.mapWidth= map.width;
		this.mapHeight= map.height;	
		
		this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
		this.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
		
		this.addChild(map);
	}
	
	
	private function onMouseWheel(e:MouseEvent):void //OK
	{
		var delta:int = e.delta * 3;
		if (e.shiftKey)
		{
			delta /= 3;
		}
		if (e.altKey)
		{
			delta *= 3;
		}
		if (e.ctrlKey)
		{
			this.x += delta * blockWidth;
		}
		else
		{
			this.y += delta * blockHeight;
		}
	}
	private function onMouseUp(e:MouseEvent):void
	{
		if(downEvent == null)
			return;
		upEvent = e;
		
		var bx:Number = downEvent.localX;
		var by:Number = downEvent.localY;
		var ex:Number = e.localX;
		var ey:Number = e.localY;
		
		
		
		
		var ref:Shape;
		for (var i:int = shapes.length-1; i>=0; i--)
		{
			if ((shapes[i] as Shape).hitTestPoint(downEvent.stageX,downEvent.stageY))
			{
				ref = shapes[i];
				break;
			}
		}
		
		if (e.altKey && !e.ctrlKey && !e.shiftKey)
		{//remove
			removePixel(e.stageX,e.stageY);
		}
		else if(e.ctrlKey && !e.altKey && !e.shiftKey)
		{//ctrl key, drag
			if(ref != null)
			{
				ref.x += ex-bx;
				ref.y += ey-by;
				label.setText(shapesInfo[i][3]);
				shapesInfo[i][0] = ex;
				shapesInfo[i][1] = ey;
			}
		}
		else if(e.shiftKey && i != -1 && !e.ctrlKey && !e.altKey)
		{//shift key, modify tag
			shapesInfo[i][3] = label.getText();
		}
		else if(e.ctrlKey && e.altKey && i!=-1)
		{
			var scale:int = 2;
			ref.graphics.clear();
			ref.graphics.beginFill(0xFF0000, 0.8);
			ref.graphics.lineStyle(0);
			ref.graphics.drawCircle(shapesInfo[i][0],shapesInfo[i][1],shapesInfo[i][2]+scale);
			ref.graphics.endFill();
			shapesInfo[i][2] += scale;
		}
		else
		{//add new mark
			drawCircle(bx,by,Point.distance(new Point(bx,by), new Point(ex,ey)),label.getText());
		}
		
	}
	private function onMouseDown(e:MouseEvent):void
	{
		downEvent = e;
	}
	
	private function drawCircle(beginX:Number, beginY:Number, r:Number, label:String):void
	{
		var rect:Shape = new Shape();
		rect.graphics.beginFill(0xFF0000,0.75);
		rect.graphics.lineStyle(0);
		rect.graphics.drawCircle(beginX,beginY,r);
		rect.graphics.endFill();
		
		addShape(rect);
		
		// important.
		addInfo(beginX,beginY,r,label);
		
	}
	public function removePixel(beginX:Number, beginY:Number):void
	{
		for (var i:int = shapes.length-1; i>=0; i--)
		{
			if ((shapes[i] as Shape).hitTestPoint(beginX,beginY))
			{
				this.removeChild(shapes[i]);
				shapes.splice(i,1);
				shapesInfo.splice(i,1);
				break;
			}
		}
	}
	private function addShape(s:Shape):void
	{
		this.addChild(s);
		shapes.push(s);
	}
	private function addInfo(...params):void
	{
		shapesInfo.push(params);
	}
	public function undo():void
	{
		if (shapes.length != 0)
		{
			this.removeChild(shapes.pop());
			shapesInfo.pop();
		}
	}
	public function loadXML(ba:ByteArray):void
	{
		var mapInfoArray:Array = Asx3mer.instance.fromXML(ba.readObject() as XML) as Array;
		mapWidth = mapInfoArray[0];
		mapHeight = mapInfoArray[1];
		blockWidth = mapInfoArray[2];
		blockHeight = mapInfoArray[3];
		
		var shapesInfoCopy:Array = Asx3mer.instance.fromXML(ba.readObject() as XML) as Array;
		
		//clear old shape;
		for (var iao:int = 0; iao < shapes.length; iao++)
		{
			this.removeChild(shapes[iao]);
		}
		shapes = new Array();
		
		//clear old shapeInfo;
		this.shapesInfo = new Array();
		
		// add new shapes
		for (var i:int = 0; i < shapesInfoCopy.length; i++)
		{
			var item:Array = shapesInfoCopy[i];
			this.drawCircle(item[0],item[1], item[2], item[3]);
		}
	}
	public function saveXML():ByteArray
	{
		var ba:ByteArray = new ByteArray();
		
		var mapInfo:Array = new Array(mapWidth, mapHeight, blockWidth, blockHeight);
		var mapInfoXml:XML = Asx3mer.instance.toXML(mapInfo);
		
		//convert object to XML
		var xmlObj:XML=Asx3mer.instance.toXML(shapesInfo);
		//			trace(xmlObj);  
		
		ba.writeObject(mapInfoXml);
		ba.writeObject(xmlObj);
		return ba;
	}
	
	public function saveBinary():ByteArray
	{
		var ba:ByteArray = new ByteArray();
		
		ba.writeShort(shapesInfo.length);
		ba.writeShort(mapWidth);
		ba.writeShort(mapHeight);
		ba.writeShort(blockWidth);
		ba.writeShort(blockHeight);
		
		for (var i:int = 0; i < shapesInfo.length; i++)
		{
			var item:Array = shapesInfo[i];
			ba.writeShort(item[0]);
			ba.writeShort(item[1]);	
//			radius omitted.
//			ba.writeShort(item[2]);	
			ba.writeUTF(item[3]);
		}
		ba.position = 0;
		return ba;
	}
	public function loadBinary(ba:ByteArray):void
	{
		var len:int = ba.readUnsignedShort();
		var mW:int = ba.readUnsignedShort();
		var mH:int = ba.readUnsignedShort();
		var bW:int = ba.readUnsignedShort();
		var bH:int = ba.readUnsignedShort();
		
		for (var i:int = 0; i < shapes.length; i++)
		{
			this.removeChild(shapes[i]);
		}
		shapes = new Array();
			
		//clear old shapeInfo;
		this.shapesInfo = new Array();
			
		// add new shapes
		for (var ii:int = 0; ii < len; ii++)
		{
			this.drawCircle(ba.readUnsignedShort(),ba.readUnsignedShort(),radius,ba.readUTF());
		}
	}
	public function UIsave(type:String = Inner.BINARY_TYPE):void
	{
		var fileRef:FileReference = new FileReference();
		var ba:ByteArray;
		
		if(type == Inner.BINARY_TYPE)
		{
			ba = saveBinary();
		}
		else if (type == Inner.XML_TYPE)
		{
			ba = saveXML();
		}
		else
		{
			throw new Error("type not defined");
		}
		fileRef.save(ba);
	}
	public function UIload(type:String = Inner.BINARY_TYPE):void
	{
		var fileRef:FileReference = new FileReference();
		fileRef.browse();
		fileRef.addEventListener(Event.SELECT, onFileSelected);
		
		function onFileSelected(e:Event):void 
		{
			fileRef.addEventListener(Event.COMPLETE, onFileLoaded);
			fileRef.load();
		}
		function onFileLoaded(e:Event):void 
		{
			var ba:ByteArray = e.target.data;
			if(type == Inner.BINARY_TYPE)
			{
				loadBinary(ba);
			}
			else if (type == Inner.XML_TYPE)
			{
				loadXML(ba);
			}
			else
			{
				throw new Error("type not defined while loading");
			}
		}
	}
}